#include "testApp.h"


float testApp::lastframe;
float testApp::deltaTime;
//--------------------------------------------------------------
void testApp::setup()
{

	blend = false;
    //ofHideCursor();
    for(int i=0; i<1; i++)
    {
        addGameObject(1);
        //gameObjects.push_back(new blob(1,ofxVec2f(rand()%ofGetWidth(),rand()%ofGetHeight()),10+rand()%1050,ofxVec2f(0,0)));
    }

    for(int i=0; i<0; i++)
    {
        addGameObject(0);
        //gameObjects.push_back(new blob(0,ofxVec2f(rand()%ofGetWidth(),rand()%ofGetHeight()),10+rand()%1050,ofxVec2f(0,0)));
    }

    selectedBlob = 0;
    readyForInput = true;
    mousePosition = ofxVec2f(0,0);
    mouseDown = false;
    lastframe = ofGetElapsedTimef();
    possibleTarget = 0;

    visuals = new VisualManager(3);
    showDebugInfo = false;
    nextPixelBeat =0;
	numTypes[0] = 0;
	numTypes[1] = 0;
	test1.loadImage("data/particle.png");
	test2.loadImage("data/explosive.png");


char buffer[256];



ifstream beatfile ("data/beatdata.txt");

  if (! beatfile.is_open())
  {
     printf("Error opening file");

  }

  while (! beatfile.eof() )
  {
    beatfile.getline (buffer,100);
    //format:"00:28:92 M"
    vector<string> result = ofSplitString(buffer, " ");
    if(result.size()==2)
    {
        //parse time to ms
         vector<string> timeResult = ofSplitString(result[0], ":");

        if(timeResult.size()==3)
        {
            BeatData b;

            int ms = 0;
            ms +=ofToInt(timeResult[0])*60*1000;
            ms +=ofToInt(timeResult[1])*1000;
            ms +=ofToInt(timeResult[2])*10;
            b.time=ms;
            b.type = result[1][0];
            BeatDataTimes.push_back(b);
           // printf(" %s is ceonverted to %i \n",buffer,b.time);
        }
    }

  }
   sort (BeatDataTimes.begin(), BeatDataTimes.end(), TimeBeatCompare);



	//BeatDataTimes.push_back()
currentBeatIndex = 0;
	beatfile.close();
	printf("\n Loaded %i number of beat data lines \n",BeatDataTimes.size());

}
bool TimeBeatCompare (BeatData i,BeatData j) { return (i.time<j.time); }
void testApp::addGameObject(int type)
{
    numTypes[type]++;
    gameObjects.push_back(new blob(type,ofxVec2f(rand()%ofGetWidth(),rand()%ofGetHeight()),10+rand()%1050,ofxVec2f(0,0)));
}

//--------------------------------------------------------------
void testApp::update()
{

    deltaTime =  ofGetElapsedTimef()-lastframe;
    lastframe = ofGetElapsedTimef();

    BeatData b = BeatDataTimes[currentBeatIndex];
    while(b.time<ofGetElapsedTimeMillis())
    {
        if(b.type=='M')
            printf("Main beat \n");
        else if(b.type=='B')
            printf("bass beat \n");
        else
            printf("?? beat %c \n",b.type);

        currentBeatIndex++;
        b = BeatDataTimes[currentBeatIndex];
    }

    if(explosionParticles.size()==0)
        readyForInput = true;
    else
        readyForInput = false;


    for(int i=0; i<gameObjects.size(); i++)
    {

        gameObjects[i]->update();

        if(mouseDown)
        {
            gameObjects[i]->interact(mousePosition);
        }


        gameObjects[i]->testIfFriend(gameObjects);
       for(int j=0; j<gameObjects.size(); j++)
        {
            if(j==i)
                continue;
            // if(i!=j && !gameObjects[i]->dead && !gameObjects[j]->dead)
            gameObjects[i]->attract(gameObjects[j]->getPosition(),gameObjects[j]->mass);


        }

        if(gameObjects[i]->readyToExplode && !gameObjects[i]->exploding)
        {
            vector<explosionParticle*> newExplosion = gameObjects[i]->explode();

            for(int j=0; j<newExplosion.size(); j++)
            {
                newExplosion[j]->setTarget(gameObjects[i]);
                explosionParticles.push_back(newExplosion[j]);
            }
            if(explosionParticles.size()>settings::MAX_EXPLOSION_PARTICLES)
                explosionParticles.erase(explosionParticles.begin(),explosionParticles.begin()+explosionParticles.size()-settings::MAX_EXPLOSION_PARTICLES);

            //Create new explosion
            explosions.push_back(new explosion(gameObjects[i]->getPosition(),gameObjects[i]->getExplosionRadius()));
        }

    }

    for(int i=0; i<explosionParticles.size(); i++)
    {

        if(!explosionParticles[i]->lost)
        {

            explosionParticles[i]->lost = true;



            explosionParticles[i]->explode();
            explosionParticles[i]->maxVelocity = 400;
            explosionParticles[i]->velocity *= ofRandom(2,10);


        }


        if(explosionParticles[i]->dead)
            continue;
        explosionParticles[i]->update();


    }



    for(int i=0; i<explosions.size(); i++)
    {
        explosions[i]->update();
        if(readyForInput)
            explosions[i]->die();
    }

	while(numTypes[1] < 1)
    {
		addGameObject(1);
    }
	visuals->update();

	if(nextPixelBeat<ofGetElapsedTimef())
    {
        nextPixelBeat = ofGetElapsedTimef()+2;
        visuals->beatPixelSize(0.04f,0.4f,8);
    }
	if(!(ofGetFrameNum()%10))
		return;
    //Cleanup:
    vector<int> toDel;
    for(int i=explosionParticles.size()-1; i>=0; i--)
    {
        if(explosionParticles[i]->dead)
            toDel.push_back(i);

    }
    for(int i=0; i<toDel.size(); i++)
    {
        explosionParticles.erase(explosionParticles.begin()+toDel[i]);
    }
    toDel.clear();

    for(int i=gameObjects.size()-1; i>=0; i--)
    {
        if(gameObjects[i]->shouldRemove())
        {
            numTypes[gameObjects[i]->type]--;
            toDel.push_back(i);
        }
    }
    for(int i=0; i<toDel.size(); i++)
    {
        gameObjects.erase(gameObjects.begin()+toDel[i]);
    }
    toDel.clear();



    if(gameObjects.size()<settings::NUMBER_OF_BLOBS && nextBlobSpawn<ofGetElapsedTimef() )
    {
        addGameObject(0);

        if(readyForInput)
            nextBlobSpawn = ofGetElapsedTimef()+settings::BLOB_SPAWN_INTERVAL;
        else
            nextBlobSpawn = ofGetElapsedTimef()+settings::BLOB_SPAWN_INTERVAL_INGAME;
    }

    //Cleanup:
    toDel.clear();
    for(int i=explosions.size()-1; i>=0; i--)
    {
        if(explosions[i]->dead)
            toDel.push_back(i);

    }
    for(int i=0; i<toDel.size(); i++)
    {
        explosions.erase(explosions.begin()+toDel[i]);

    }




}

//--------------------------------------------------------------
void testApp::draw()
{


	ofEnableAlphaBlending();
	ofSetColor(255,255,255);
	glEnable(GL_BLEND);

	//glBlendEquation(GL_FUNC_ADD);
	//glBlendFunc(GL_SRC_COLOR, GL_ONE);


	//visuals->draw();
	//visuals->draw();

	//ofRect(10,10,400,400);

	visuals->backImage->draw(0,0,800,600);


    visuals->beginLayerBuffer(0);




	/*if(blend)
		glBlendFunc(GL_ONE, GL_DST_ALPHA);
	*/



	//visuals->draw();
	//ofSetColor(255,255,255);
	//ofCircle(200,200,100);


	//ofDisableAlphaBlending();
//return;
//
  //  visuals->beginLayerBuffer(0);

    //ofSetColor(255,0,190,255);
   // ofRect(0,0,ofGetWidth(),ofGetHeight());

    ofSetColor(255,255,255,255);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    for(int i=0; i<explosions.size(); i++)
    {
        explosions[i]->draw();
    }

   for(int i=0; i<explosionParticles.size(); i++)
    {
        if(explosionParticles[i]->dead)
            continue;
        explosionParticles[i]->draw();
    }


    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    ofSetColor(150,100,0,200);
    ofCircle(mousePosition.x,mousePosition.y,4);
    ofSetColor(150,100,0,110);
    ofCircle(mousePosition.x,mousePosition.y,10);




ofSetColor(255,255,255,255);
ofCircle(mousePosition.x,mousePosition.y,100);

visuals->endLayerBuffer(0);
glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
visuals->draw(0);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
//visuals->beginLayerBuffer(1);

//visuals->endLayerBuffer(0);

visuals->beginLayerBuffer(1);
visuals->frontVideo.draw(0,0,800,600);


glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

visuals->draw(0);


visuals->endLayerBuffer(1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
visuals->draw(1);


//visuals->endLayerBuffer(1);
    //glBlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA);

/*
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);


    visuals->beginLayerBuffer(1);
    visuals->frontVideo.draw(0,0,800,600);
ofSetColor(255,255,255,100);
    //visuals->endLayerBuffer(0);
glBlendFunc(GL_ZERO,GL_ONE_SRC_ALPHA);
    ofCircle(mousePosition.x,mousePosition.y,50);

glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
visuals->endLayerBuffer(1);
*/
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    //visuals->endLayerBuffer(0);




    for(int j=0; j<gameObjects.size(); j++)
    {
gameObjects[j]->draw();

        for(int k=0; k<gameObjects.size(); k++)
        {
            if(j!=k)
                gameObjects[j]->drawFriend(gameObjects[k]);
        }

        //Check if close and we should draw drag line
        if(mouseDown)
        {

            gameObjects[j]->drawLineTo(mousePosition);
        }

    }
	//glBlendFunc(GL_ONE, GL_ONE);


    ofFill();

   //  visuals->endLayerBuffer(1);

    //visuals->endLayerBuffer(1);
   // visuals->beginLayerBuffer(2);



   // visuals->endLayerBuffer(0);




    if(showDebugInfo)
    {
        ofSetColor(0x000000);
        ofNoFill();


        string info = "number of blobs: " + ofToString(gameObjects.size(),3) + "\n" +
                      "number of blob type 0: " + ofToString(numTypes[0]) + "\n" +
                      "number of blob type 1: " + ofToString(numTypes[1]) + "\n" +
                      "number of particles: " + ofToString(explosionParticles.size(),3) + "\n"
                      "frame rate: " + ofToString(ofGetFrameRate(),1) + "\n" +
                      "pixel size: " + ofToString(visuals->pixelSize,1) + "\n";
        ofFill();
        ofSetColor(0xE5A93F);
        ofRect(10,10,300,100);
        ofSetColor(0x000000);
        ofDrawBitmapString(info,30,30);
    }



}

//--------------------------------------------------------------
void testApp::keyPressed  (int key)
{

    switch (key)
    {
    case 'a':
        visuals->beatPixelSize(0.07f,0.5f,9);
        break;
    case 'd':
        showDebugInfo = !showDebugInfo;
        break;
	case 'b':
        blend = !blend;
        break;
    }
}

//--------------------------------------------------------------
void testApp::keyReleased  (int key)
{

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y )
{
    mouseDown = false;
    mousePosition.x = x;
    mousePosition.y = y;
    //TODO:When playing the player should be able to push/drag/gravity around the particles!

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button)
{

    mousePosition.x = x;
    mousePosition.y = y;
    mouseDown = true;

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button)
{

    mouseDown = true;

   /* for(int i=0; i<gameObjects.size(); i++)
    {
        ofxVec2f diff = gameObjects[i]->getPosition()-ofxVec2f(mouseX,mouseY);
        if(diff.length()<gameObjects[i]->getRadius())
        {
            gameObjects[i]->readyToExplode = true;
        }
    }*/


}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button)
{
    mouseDown = false;
}

void testApp::windowResized(int w, int h)
{

}


//void testApp::findPossibleTarget(blob* from)
//{
//    //select target
//    blob* bestBlob = 0;
//    float bestMass = 0;
//    for(int k=0; k<gameObjects.size(); k++)
//    {
//        if((gameObjects[k]->getPosition()-from->getPosition()).length()<from->getExplosionRadius()+gameObjects[k]->getRadius() && gameObjects[k]!=from && !gameObjects[k]->dead)
//        {
//            if(bestMass<gameObjects[k]->mass)
//            {
//                bestMass = gameObjects[k]->mass;
//                bestBlob = gameObjects[k];
//            }
//        }
//    }
//    if(bestBlob!=0)
//    {
//        possibleTarget = bestBlob;
//        possibleTarget->possibleTarget = true;
//    }
//    else //If no target go for random
//    {
//        possibleTarget = 0;
//    }
//}
